
package cn.ch.basic.inteceptor;

import cn.ch.basic.jwt.JwtUtils;
import cn.ch.basic.jwt.LoginData;
import cn.ch.basic.jwt.Payload;
import cn.ch.basic.util.RsaUtils;
import cn.ch.org.mapper.EmployeeMapper;
import cn.ch.system.anno.PreAuthorize;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.security.PublicKey;
import java.util.List;

@Component
@Slf4j
public class LoginInteceptor implements HandlerInterceptor {
    /*  @Autowired 使用jwt来存储数据，不再使用redis存储
      private RedisTemplate redisTemplate;
    */
    @Autowired
    private EmployeeMapper employeeMapper;
    @Value("${jwt.rsa.pub}")
    private String pubKey;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //第一种，存储数据到redis
      /*  //1.获取请求头里面的token
        String token = request.getHeader("TOKEN");
        //2.校验token不能为空
        if (!StringUtils.isEmpty(token)) {
            Object loginTmp = redisTemplate.opsForValue().get(token);
            //3.1 拿不到token，登录失败，或者token有问题 ，阻止放行
            if (loginTmp != null) {
                //3.2 拿到了token，刷新token过期时间，放行
                redisTemplate.opsForValue().set(
                        token,
                        loginTmp,
                        30,
                        TimeUnit.MINUTES);
                        */

        //第二种，通过jwt加密存储
        //1.获取请求头中的token
        String token = request.getHeader("U-TOKEN");
        //2.校验token是否为空
        if(!StringUtils.isEmpty(token)) {
            //3.获取公钥,通过公钥解密对应token
            PublicKey publicKey = RsaUtils.getPublicKey(JwtUtils.class.getClassLoader().getResource(pubKey).getFile());
            //4.解密
            Payload<LoginData> payload = JwtUtils.getInfoFromToken(token, publicKey, LoginData.class);
            LoginData loginData = payload.getLoginData();
            //5.判断用户类型
            if (loginData.getUser()!=null){
                return true;//前端用户
            }
            //判断用户是否有权限
            HandlerMethod method = (HandlerMethod) handler;//handler指@Controller注解下的"完整"方法名
            //6.获取方法上的注解
            PreAuthorize authorize = method.getMethodAnnotation(PreAuthorize.class);
            if (authorize != null) {//有这个注解
                String value = authorize.value();//获取此访问此方法所需要的权限
                System.out.println("需要的权限信息:"+value);
                //获取logininfo的权限信息
                List<String> permissions =  loginData.getPermissions();
                //System.out.println("权限信息:");
                permissions.forEach(System.out::println);
                if (permissions.contains(value)){//有权限
                    //有权限访问了
                    return true;
                }
                log.info("普通用户");
                //没有权限
                response.setContentType("application/json;charset=utf-8");//设置响应类型
                PrintWriter writer = response.getWriter();//获取响应的输出流
                writer.print("{\"success\":false,\"message\":\"noPermission\"}");
                writer.flush();
                writer.close();
                return false;
            }else {
                return true;
            }
        }
        //登录验证失败
        response.setContentType("application/json;charset=utf-8");//设置响应类型
        PrintWriter writer = response.getWriter();//获取响应的输出流
        writer.print("{\"success\":false,\"message\":\"noLogin\"}");
        writer.flush();
        writer.close();
        //阻止放行
        return false;
    }
}

           /* PublicKey publicKey = RsaUtils.getPublicKey(JwtUtils.class.getClassLoader().getResource(pubKey).getFile());
            Payload<LoginData> payload = JwtUtils.getInfoFromToken(token, publicKey, LoginData.class);
            //3.1 拿不到  登录失效或者是个瓦token 阻止放行
            if (payload != null) {
                //3.2 拿到了  刷新token过期时间，方案待定
                *//*if(payload.getExpiration().after(new Date(System.currentTimeMillis()))){
                    //刷新过期时间....
                 }*//*
                //还需要看当前这个人是否有权限访问资源
                LoginData loginData = payload.getLoginData();
                if (loginData.getUser() != null) {
                    //1.如果是前端用户 user ，不需要校验任何权限，直接放行即可
                    return true;//放行
                }
                //2.如果是后端员工employee来操作的时候，才需要校验资源的访问权限
                //2.1 哪些请求需要校验权限 （答：打了自定义注解PreAuthorize权限的方法）
                HandlerMethod handlerMethod = (HandlerMethod) handler;
                PreAuthorize preAuthorize = handlerMethod.getMethodAnnotation(PreAuthorize.class);
                //3.判断preAuthorize 是否有值
                if (preAuthorize == null) {
                    //3.2 没有，放行  公共资源不需要校验权限
                    return true;
                }
                //3.1 有，校验是否有权限访问
                String sn = preAuthorize.value();//需要校验当前登录人，是否有权限访问该资源
                //查询出当前登录人所拥有的权限
                List<String> ownPermissions = loginData.getPermissions();//从jwt中解析得到权限信息
                if (ownPermissions.contains(sn)) {
                    return true;//终于有权限访问了
                }
                //告诉他没有权限，请他去联系管理员
                response.setCharacterEncoding("UTF-8");
                response.setContentType("application/json;charset=utf-8");
                PrintWriter writer = response.getWriter();
                writer.print("{\"success\":false,\"message\":\"noPermission\"}");
                writer.flush();
                writer.close();
                return false;//阻止放行
            }
        }*/